package com.liqw.core;

import lombok.extern.slf4j.Slf4j;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;

/**
 * 登录服务类（处理登录流程、状态验证、第三方登录检测）
 */
@Slf4j
public class LoginService {
    private final WebDriver driver;
    private final String originalDomain; // 目标网站域名
    private String currentUrl; // 当前页面URL
    private final Set<String> visitedUrls = ConcurrentHashMap.newKeySet(); // 已访问URL
    private final Map<String, Boolean> domainLoginStatus = new ConcurrentHashMap<>(); // 域名登录状态
    private final List<Consumer<WebDriver>> pageChangeListeners = new ArrayList<>(); // 页面变化监听器
    private boolean isInThirdPartyFlow = false; // 是否在第三方登录流程中
    private final AtomicBoolean isMonitoring = new AtomicBoolean(true); // 是否监控页面变化

    public LoginService(WebDriver driver, String targetUrl) {
        this.driver = driver;
        this.originalDomain = WebDriverUtils.extractDomain(targetUrl);
        this.currentUrl = targetUrl;
        // 初始化监听器
        initListeners();
    }

    /**
     * 初始化页面变化监听器（职责：登录状态检测、域名变化检测等）
     */
    private void initListeners() {
        pageChangeListeners.add(this::printPageInfo); // 打印页面信息
        pageChangeListeners.add(this::checkDomainChange); // 检测域名变化
        pageChangeListeners.add(this::checkThirdPartyLogin); // 检测第三方登录
        pageChangeListeners.add(this::checkLoginStateOnPageChange); // 检测登录状态
    }

    /**
     * 执行登录流程（打开目标页、监控登录状态）
     */
    public boolean doLogin() {
        try {
            driver.get(currentUrl);
            visitedUrls.add(currentUrl);
            log.info("已打开目标网站: {}", originalDomain);
            log.info("请在浏览器中完成登录（支持手动输入或第三方登录）");
            log.info("登录完成后系统将自动检测...");

            // 启动页面监控线程（检测登录状态变化）
            Thread monitorThread = new Thread(this::monitorPageChanges);
            monitorThread.start();
            monitorThread.join(); // 等待登录完成

            // 验证最终登录状态
            return verifyLoginState();
        } catch (Exception e) {
            log.error("登录流程异常", e);
            return false;
        }
    }

    /**
     * 监控页面变化（检测URL变化并触发监听器）
     */
    private void monitorPageChanges() {
        try {
            while (isMonitoring.get()) {
                log.info("正在监控登陆页面变化...");
                String newUrl = driver.getCurrentUrl();
                if (!newUrl.equals(currentUrl)) {
                    currentUrl = newUrl;
                    visitedUrls.add(currentUrl);
                    log.info("检测到页面跳转: {}", currentUrl);
                    // 触发所有监听器
                    pageChangeListeners.forEach(listener -> listener.accept(driver));
                }
                // 降低监控频率（避免占用过高资源）
                Thread.sleep(500);
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt(); // 恢复中断状态
        } catch (Exception e) {
            log.error("页面监控异常", e);
        }
    }

    /**
     * 打印页面基本信息（辅助调试）
     */
    private void printPageInfo(WebDriver driver) {
        String domain = WebDriverUtils.extractDomain(currentUrl);
        log.info("当前域名: {}", domain);
        log.info("页面标题: {}", driver.getTitle());
        log.info("已访问URL数量: {}", visitedUrls.size());
    }

    /**
     * 检测域名变化（判断是否跳转到登录页或第三方域名）
     */
    private void checkDomainChange(WebDriver driver) {
        long start = System.currentTimeMillis();
        String domain = WebDriverUtils.extractDomain(currentUrl);
        if (!domainLoginStatus.containsKey(domain)) {
            domainLoginStatus.put(domain, false);
            log.info("访问新域名: {}", domain);

            // 若跳转到非目标域名，提示用户在此登录
            if (!domain.equals(originalDomain) && !isInThirdPartyFlow) {
                log.info("检测到跳转至登录相关域名，请在此页面完成登录");
            }
        }
        log.info("------------------------ checkDomainChange cost {} ms", System.currentTimeMillis() - start);
    }

    /**
     * 检测第三方登录选项（微信、QQ等）
     */
    private void checkThirdPartyLogin(WebDriver driver) {
        long start = System.currentTimeMillis();
        if (!isLoginPage(driver)) {
            log.info("------------------------ checkThirdPartyLogin isLoginPage cost {} ms", System.currentTimeMillis() - start);
            return;
        }
        log.info("检测到登录页面，正在查找第三方登录选项...");

        // 常见第三方登录选择器（可根据实际网站扩展）
        Map<String, String> thirdPartySelectors = new HashMap<>();
        thirdPartySelectors.put("微信", "img[src*=\"loginWechat\"]"); // 包含loginWechat的图片（模糊匹配）
        thirdPartySelectors.put("QQ", "img[src*=\"loginQQ\"]"); // 包含loginQQ的图片（模糊匹配）

        // 查找并提示第三方登录选项
        Map<String, WebElement> foundOptions = new HashMap<>();
        for (Map.Entry<String, String> entry : thirdPartySelectors.entrySet()) {
            WebElement element = WebDriverUtils.waitForElementVisible(driver,
                    org.openqa.selenium.By.cssSelector(entry.getValue()));
            if (element != null) {
                foundOptions.put(entry.getKey(), element);
            }
        }

        if (!foundOptions.isEmpty()) {
            log.info("发现第三方登录选项: {}", foundOptions.keySet());
            isInThirdPartyFlow = true;
        } else {
            log.info("未发现第三方登录选项，请使用账号密码登录");
        }
        log.info("------------------------ checkThirdPartyLogin cost {} ms", System.currentTimeMillis() - start);
    }

    /**
     * 判断当前页面是否为登录页
     */
    private boolean isLoginPage(WebDriver driver) {
        long start = System.currentTimeMillis();
        String title = driver.getTitle().toLowerCase();
        // 标题包含登录关键词
        if (title.contains("登录") || title.contains("login") || title.contains("sign in")) {
            log.info("------------------------ isLoginPage contains cost {} ms", System.currentTimeMillis() - start);
            return true;
        }
        // 页面包含登录表单元素
        org.openqa.selenium.By[] loginIndicators = {
//                org.openqa.selenium.By.cssSelector("#login-button"),
//                org.openqa.selenium.By.cssSelector("#jorenoeForm > button.button_active"),
                org.openqa.selenium.By.xpath("/html/body/div[1]/div/div[2]/div[3]/div[1]/div[1]/form/button")

        };
        for (org.openqa.selenium.By indicator : loginIndicators) {
            WebElement element = WebDriverUtils.waitForElementVisible(driver, indicator);
            if (element != null) {
                log.info("------------------------ isLoginPage indicator cost {} ms", System.currentTimeMillis() - start);
                return true;
            }
        }
        log.info("------------------------ isLoginPage indicator cost {} ms", System.currentTimeMillis() - start);
        return false;
    }

    /**
     * 页面变化时检查登录状态（登录成功后停止监控）
     */
    private void checkLoginStateOnPageChange(WebDriver driver) {
        long start = System.currentTimeMillis();
        String domain = WebDriverUtils.extractDomain(currentUrl);
        boolean isLoggedIn = verifyLoginState();

        if (isLoggedIn && !domainLoginStatus.getOrDefault(domain, false)) {
            domainLoginStatus.put(domain, true);
            isMonitoring.set(false); // 停止监控
            log.info("域名 [{}] 登录成功！", domain);

            // 第三方登录后可能跳转回原域名
            if (!domain.equals(originalDomain) && isInThirdPartyFlow) {
                log.info("第三方登录流程完成，可能自动跳转回原域名");
                isInThirdPartyFlow = false;
            }
        }
        log.info("------------------------ checkLoginStateOnPageChange cost {} ms", System.currentTimeMillis() - start);
    }

    /**
     * 验证登录状态（通过登录成功标识判断）
     */
    public boolean verifyLoginState() {
        long start = System.currentTimeMillis();
        // 登录成功标识（可根据实际网站调整）
        By[] successIndicators = {
//                By.cssSelector("i.icon-switch2"), // 登出按钮（常见于登录后）
//                By.cssSelector(".dropdown-user") // 用户信息区域
                By.xpath("/html/body/app-root/div[1]/div/div/div[3]/ul[2]/li[3]") // 用户信息区域
        };

        // 检查是否存在登录成功标识
        for (By indicator : successIndicators) {
            WebElement element = WebDriverUtils.waitForElementVisible(driver, indicator);
            if (element != null) {
                log.info("检测到登录成功标识");
                log.info("------------------------ verifyLoginState indicator cost {} ms", System.currentTimeMillis() - start);
                return true;
            }
        }

        // 检查URL是否包含认证参数（如token、user_id）
        if (currentUrl.contains("token=") || currentUrl.contains("user_id=")) {
            log.info("URL包含认证参数，判断为已登录");
            log.info("------------------------ verifyLoginState contains cost {} ms", System.currentTimeMillis() - start);
            return true;
        }
        log.info("------------------------ verifyLoginState cost {} ms", System.currentTimeMillis() - start);
        return false;
    }

    /**
     * 打印用户信息（登录后调用）
     */
    public void printUserInfo() {
        log.info("=== 用户信息 ===");
        // 尝试获取用户名（选择器需根据实际网站调整）
        WebElement userNameElement = WebDriverUtils.waitForElementVisible(driver,
                org.openqa.selenium.By.cssSelector(".dropdown-user > a > span"));
        log.info("当前用户: {}", userNameElement != null ? userNameElement.getText() : "未获取到");
        log.info("当前域名: {}", WebDriverUtils.extractDomain(driver.getCurrentUrl()));
        log.info("===============\n");
    }
}